"""
视频素材入库命令

提供视频素材自动化入库的CLI命令。
"""

import json
import sys
from pathlib import Path
from typing import Optional, Dict, Any, List

import click
from loguru import logger

from src.services.config_service import config_service


@click.group(name="material")
def material_group():
    """视频素材入库管理"""
    pass


@material_group.command()
@click.argument('project_directory', type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option('--config', '-c', type=click.Path(exists=True), help='配置文件路径')
@click.option('--max-duration', type=float, default=3.0, help='最大切片时长(秒)')
@click.option('--min-duration', type=float, default=1.0, help='最小切片时长(秒)')
@click.option('--confidence', type=float, default=0.7, help='AI分类置信度阈值')
@click.option('--use-mock-ai', is_flag=True, help='使用模拟AI服务')
@click.option('--move-files', is_flag=True, help='移动文件而不是复制')
@click.option('--no-shot-detection', is_flag=True, help='禁用镜头检测')
@click.option('--dry-run', is_flag=True, help='试运行模式，不实际处理文件')
@click.option('--verbose', '-v', is_flag=True, help='详细输出')
@click.option('--async-mode', is_flag=True, help='使用异步模式执行完整工作流')
def process(project_directory: str,
           config: Optional[str],
           max_duration: float,
           min_duration: float,
           confidence: float,
           use_mock_ai: bool,
           move_files: bool,
           no_shot_detection: bool,
           dry_run: bool,
           verbose: bool,
           async_mode: bool):
    """
    处理视频素材入库
    
    PROJECT_DIRECTORY: 项目目录路径
    """
    
    try:
        # 设置日志级别
        if verbose:
            logger.remove()
            logger.add(sys.stderr, level="DEBUG")

        logger.info(f"开始处理项目: {project_directory}")

        # 加载配置
        workflow_config = load_workflow_config_sync(config)

        # 更新配置参数
        workflow_config.update({
            "base_directory": project_directory,
            "max_segment_duration": max_duration,
            "min_segment_duration": min_duration,
            "confidence_threshold": confidence,
            "use_mock_ai": use_mock_ai,
            "move_files": move_files,
            "enable_shot_detection": not no_shot_detection
        })

        if dry_run:
            logger.info("试运行模式，将显示处理计划但不实际执行")
            show_processing_plan_sync(project_directory, workflow_config)
        elif async_mode:
            logger.info("使用异步模式执行完整工作流")
            # 创建并运行异步工作流
            import subprocess
            import sys

            # 构建命令参数
            cmd_args = [
                sys.executable, "run_material_workflow.py", project_directory,
                f"--max-duration={max_duration}",
                f"--min-duration={min_duration}",
                f"--confidence={confidence}"
            ]

            if use_mock_ai:
                cmd_args.append("--use-mock-ai")
            if move_files:
                cmd_args.append("--move-files")
            if no_shot_detection:
                cmd_args.append("--no-shot-detection")
            if verbose:
                cmd_args.append("--verbose")

            try:
                # 执行异步工作流脚本
                result = subprocess.run(cmd_args, check=True, capture_output=True, text=True)
                click.echo(result.stdout)
                if result.stderr:
                    click.echo(result.stderr, err=True)
            except subprocess.CalledProcessError as e:
                logger.error(f"异步工作流执行失败: {e}")
                if e.stdout:
                    click.echo(e.stdout)
                if e.stderr:
                    click.echo(e.stderr, err=True)
                sys.exit(1)
            except FileNotFoundError:
                logger.error("未找到 run_material_workflow.py 脚本")
                click.echo("💡 请确保 run_material_workflow.py 文件存在于项目根目录")
                sys.exit(1)
        else:
            logger.info("显示处理计划（使用 --async-mode 执行完整工作流）")
            show_processing_plan_sync(project_directory, workflow_config)
            click.echo("\n💡 提示: 使用 --async-mode 参数执行完整的工作流，或使用 run_material_workflow.py 脚本")

    except Exception as e:
        logger.error(f"处理失败: {e}")
        if verbose:
            import traceback
            traceback.print_exc()
        sys.exit(1)


@material_group.command()
@click.argument('project_directory', type=click.Path())
@click.option('--template', type=click.Choice(['basic', 'advanced', 'custom']), default='basic', help='目录模板')
def init(project_directory: str, template: str):
    """
    初始化项目目录结构
    
    PROJECT_DIRECTORY: 要创建的项目目录路径
    """
    logger.info(f"初始化项目目录: {project_directory}")
    
    project_path = Path(project_directory)
    project_path.mkdir(parents=True, exist_ok=True)
    
    # 根据模板创建目录结构
    if template == 'basic':
        directories = [
            "未分类", "AI素材", "产品展示", "产品使用", 
            "模特试穿", "废弃素材", "成品"
        ]
    elif template == 'advanced':
        directories = [
            "未分类", "AI素材", "产品展示", "产品使用",
            "模特试穿", "废弃素材", "剪映模板", "成品",
            "temp", "logs", "reports"
        ]
    else:  # custom
        directories = click.prompt(
            "请输入目录名称（用逗号分隔）",
            default="未分类,AI素材,产品展示,产品使用,模特试穿,废弃素材,成品"
        ).split(',')
    
    # 创建目录
    for dir_name in directories:
        dir_path = project_path / dir_name.strip()
        dir_path.mkdir(exist_ok=True)
        logger.info(f"  ✓ 创建目录: {dir_name.strip()}")
    
    # 创建配置文件
    config_file = project_path / "workflow_config.yaml"
    if not config_file.exists():
        create_default_config(config_file)
        logger.info(f"  ✓ 创建配置文件: {config_file}")
    
    # 创建数据库文件
    db_file = project_path / "db.json"
    if not db_file.exists():
        create_empty_database(db_file)
        logger.info(f"  ✓ 创建数据库文件: {db_file}")
    
    logger.info(f"项目目录初始化完成: {project_path.absolute()}")


@material_group.command()
@click.argument('project_directory', type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option('--format', 'output_format', type=click.Choice(['json', 'table', 'summary']), default='summary', help='输出格式')
def status(project_directory: str, output_format: str):
    """
    查看项目状态
    
    PROJECT_DIRECTORY: 项目目录路径
    """
    
    try:
        project_path = Path(project_directory)

        # 扫描项目状态 - 使用同步版本
        status_info = scan_project_status_sync(project_path)

        # 显示状态
        if output_format == 'json':
            click.echo(json.dumps(status_info, indent=2, ensure_ascii=False))
        elif output_format == 'table':
            show_status_table(status_info)
        else:  # summary
            show_status_summary(status_info)

    except Exception as e:
        logger.error(f"获取状态失败: {e}")
        sys.exit(1)


@material_group.command()
@click.argument('project_directory', type=click.Path(exists=True, file_okay=False, dir_okay=True))
@click.option('--category', type=str, help='指定分类')
@click.option('--format', 'output_format', type=click.Choice(['json', 'table']), default='table', help='输出格式')
def list(project_directory: str, category: Optional[str], output_format: str):
    """
    列出项目中的视频文件
    
    PROJECT_DIRECTORY: 项目目录路径
    """
    
    try:
        project_path = Path(project_directory)

        # 扫描视频文件 - 使用同步版本
        video_files = scan_video_files_sync(project_path, category)

        # 显示文件列表
        if output_format == 'json':
            click.echo(json.dumps(video_files, indent=2, ensure_ascii=False))
        else:  # table
            show_video_files_table(video_files)

    except Exception as e:
        logger.error(f"列出文件失败: {e}")
        sys.exit(1)


# 辅助函数

def load_workflow_config_sync(config_path: Optional[str]) -> Dict[str, Any]:
    """加载工作流配置（同步版本）"""
    if config_path:
        # 从指定文件加载
        config_data = config_service.load_config_file(config_path)
        return config_data.get('workflow', {})
    else:
        # 使用默认配置
        return {
            "max_segment_duration": 3.0,
            "min_segment_duration": 1.0,
            "enable_shot_detection": True,
            "confidence_threshold": 0.7,
            "use_mock_ai": False,
            "move_files": False,
            "create_backup": True
        }


def show_processing_plan_sync(project_directory: str, config: Dict[str, Any]):
    """显示处理计划（试运行，同步版本）"""
    import os

    # 扫描未分类目录
    uncategorized_path = Path(project_directory) / config.get("uncategorized_dir", "未分类")

    if uncategorized_path.exists():
        # 简单扫描视频文件
        video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.m4v', '.3gp'}
        video_files = []

        try:
            for root, _, files in os.walk(uncategorized_path):
                for file in files:
                    if Path(file).suffix.lower() in video_extensions:
                        video_files.append(file)
        except (OSError, IOError):
            pass

        click.echo(f"📁 项目目录: {project_directory}")
        click.echo(f"📹 发现视频文件: {len(video_files)} 个")
        click.echo(f"⚙️  配置:")
        click.echo(f"   - 最大切片时长: {config.get('max_segment_duration', 3.0)}秒")
        click.echo(f"   - 镜头检测: {'启用' if config.get('enable_shot_detection', True) else '禁用'}")
        click.echo(f"   - AI置信度阈值: {config.get('confidence_threshold', 0.7)}")
        click.echo(f"   - 文件操作: {'移动' if config.get('move_files', False) else '复制'}")
        click.echo(f"   - 使用模拟AI: {'是' if config.get('use_mock_ai', False) else '否'}")

        if video_files:
            click.echo(f"\n📋 待处理文件:")
            for i, video_file in enumerate(video_files[:10], 1):
                click.echo(f"   {i}. {video_file}")
            if len(video_files) > 10:
                click.echo(f"   ... 还有 {len(video_files) - 10} 个文件")
        else:
            click.echo(f"\n📋 未分类目录中没有发现视频文件")
    else:
        click.echo(f"⚠️  未分类目录不存在: {uncategorized_path}")


def show_processing_result(result: Dict[str, Any]):
    """显示处理结果"""
    click.echo("✅ 处理完成!")
    
    # 从结果中提取统计信息
    if 'report' in result and 'statistics' in result['report']:
        stats = result['report']['statistics']
        click.echo(f"📊 处理统计:")
        click.echo(f"   - 原始视频: {stats.get('total_original_videos', 0)} 个")
        click.echo(f"   - 生成片段: {stats.get('total_segments_generated', 0)} 个")
        
        if 'category_distribution' in stats:
            click.echo(f"   - 分类分布:")
            for category, count in stats['category_distribution'].items():
                click.echo(f"     • {category}: {count} 个")


def scan_project_status_sync(project_path: Path) -> Dict[str, Any]:
    """扫描项目状态"""
    import os

    status = {
        "project_path": str(project_path),
        "directories": {},
        "total_files": 0,
        "total_size": 0
    }

    # 扫描各个目录
    directories = ["未分类", "AI素材", "产品展示", "产品使用", "模特试穿", "废弃素材", "成品"]

    # 支持的视频格式
    video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.m4v', '.3gp'}

    for dir_name in directories:
        dir_path = project_path / dir_name
        if dir_path.exists():
            # 简单的文件扫描
            video_files = []
            total_size = 0

            try:
                for root, _, files in os.walk(dir_path):
                    for file in files:
                        file_path = Path(root) / file
                        if file_path.suffix.lower() in video_extensions:
                            try:
                                file_size = file_path.stat().st_size
                                video_files.append(file_path)
                                total_size += file_size
                            except (OSError, IOError):
                                # 忽略无法访问的文件
                                pass

                status["directories"][dir_name] = {
                    "exists": True,
                    "file_count": len(video_files),
                    "total_size": total_size
                }

                status["total_files"] += len(video_files)
                status["total_size"] += total_size

            except (OSError, IOError) as e:
                status["directories"][dir_name] = {
                    "exists": True,
                    "file_count": 0,
                    "total_size": 0,
                    "error": str(e)
                }
        else:
            status["directories"][dir_name] = {"exists": False}

    return status


def scan_video_files_sync(project_path: Path, category: Optional[str] = None) -> List[Dict[str, Any]]:
    """扫描视频文件（同步版本）"""
    import os
    from datetime import datetime

    video_files = []

    # 支持的视频格式
    video_extensions = {'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.m4v', '.3gp'}

    # 确定扫描目录
    if category:
        # 扫描特定分类目录
        scan_dirs = [category]
    else:
        # 扫描所有目录
        scan_dirs = ["未分类", "AI素材", "产品展示", "产品使用", "模特试穿", "废弃素材", "成品"]

    for dir_name in scan_dirs:
        dir_path = project_path / dir_name
        if dir_path.exists():
            try:
                for root, _, files in os.walk(dir_path):
                    for file in files:
                        file_path = Path(root) / file
                        if file_path.suffix.lower() in video_extensions:
                            try:
                                stat_info = file_path.stat()
                                video_files.append({
                                    "name": file,
                                    "path": str(file_path),
                                    "size": stat_info.st_size,
                                    "category": dir_name,
                                    "modified_time": datetime.fromtimestamp(stat_info.st_mtime).isoformat()
                                })
                            except (OSError, IOError):
                                # 忽略无法访问的文件
                                pass
            except (OSError, IOError):
                # 忽略无法访问的目录
                pass

    return video_files


def show_video_files_table(video_files: List[Dict[str, Any]]):
    """显示视频文件表格"""
    if not video_files:
        click.echo("📹 没有找到视频文件")
        return

    click.echo(f"📹 找到 {len(video_files)} 个视频文件:")
    click.echo()

    for i, file_info in enumerate(video_files, 1):
        size_mb = file_info['size'] / (1024 * 1024) if file_info['size'] else 0
        click.echo(f"{i:3d}. {file_info['name']}")
        click.echo(f"     分类: {file_info['category']}")
        click.echo(f"     大小: {size_mb:.1f} MB")
        click.echo(f"     路径: {file_info['path']}")
        click.echo()


def show_status_table(status: Dict[str, Any]):
    """显示状态表格"""
    click.echo(f"📁 项目: {status['project_path']}")
    click.echo(f"📹 总文件数: {status['total_files']}")
    click.echo(f"💾 总大小: {format_file_size(status['total_size'])}")
    click.echo()
    click.echo("📂 目录详情:")
    click.echo("-" * 50)

    for dir_name, dir_info in status["directories"].items():
        if dir_info["exists"]:
            count = dir_info["file_count"]
            size = format_file_size(dir_info["total_size"])
            click.echo(f"{dir_name:12s} | {count:6d} 个文件 | {size:>10s}")
        else:
            click.echo(f"{dir_name:12s} | {'不存在':>20s}")


def show_status_summary(status: Dict[str, Any]):
    """显示状态摘要"""
    click.echo(f"📁 项目: {status['project_path']}")
    click.echo(f"📹 总文件数: {status['total_files']}")
    click.echo(f"💾 总大小: {format_file_size(status['total_size'])}")
    click.echo(f"\n📂 目录状态:")
    
    for dir_name, dir_info in status["directories"].items():
        if dir_info["exists"]:
            count = dir_info["file_count"]
            size = format_file_size(dir_info["total_size"])
            click.echo(f"   ✓ {dir_name}: {count} 个文件 ({size})")
        else:
            click.echo(f"   ✗ {dir_name}: 不存在")


def format_file_size(size_bytes: int) -> str:
    """格式化文件大小"""
    for unit in ['B', 'KB', 'MB', 'GB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.1f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.1f} TB"


def create_default_config(config_file: Path):
    """创建默认配置文件"""
    default_config = """# 视频素材入库工作流配置

workflow:
  max_segment_duration: 3.0
  min_segment_duration: 1.0
  enable_shot_detection: true
  confidence_threshold: 0.7
  use_mock_ai: false
  move_files: false
  create_backup: true

directories:
  uncategorized_dir: "未分类"
  ai_material_dir: "AI素材"
  product_display_dir: "产品展示"
  product_usage_dir: "产品使用"
  model_wearing_dir: "模特试穿"
  waste_dir: "废弃素材"
"""
    
    with open(config_file, 'w', encoding='utf-8') as f:
        f.write(default_config)


def create_empty_database(db_file: Path):
    """创建空数据库文件"""
    empty_db = {
        "videos": [],
        "last_updated": None,
        "version": "1.0.0"
    }
    
    with open(db_file, 'w', encoding='utf-8') as f:
        json.dump(empty_db, f, indent=2, ensure_ascii=False)
